using Abc.Core;
using Abc.Core.Entities;

using Furion.DatabaseAccessor;
using Furion.DependencyInjection;

using Mapster;

using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

using Tool;

using Z.Linq;

namespace Abc.Application
{
    /// <summary>
    /// 菜单表
    /// </summary>
    [ApiDescriptionSettings(Name = "Menu")]
    [ServiceFilter(typeof(ApiActionFilterAttribute))]
    public class MenuService : IMenuService, ITransient
    {
        private readonly ILogger<MenuService> _logger;
        private readonly IRepository<Menu> _menuRepository;
        private readonly ICacheService _cacheService;

        public MenuService(ILogger<MenuService> logger
     , IRepository<Menu> menuRepository
     , ICacheService cacheService)
        {
            _logger = logger;
            _menuRepository = menuRepository;
            _cacheService = cacheService;
        }

        /// <summary>
        /// 新增或更新一条
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<ResultData<string>> InsertOrUpdate(MenuInput input)
        {
            var resultdata = new ResultData<string>();
            var entities = await _cacheService.GetMenuEntities();
            if (input.Id > 0)
            {
                //if (entities.Any(o => o.MId == input.MId && o.Id != input.Id))
                //{
                //    resultdata.Errors = "唯一标识已存在";
                //    return resultdata;
                //}
                var dbentity = await _menuRepository.FindAsync(input.Id);
                input.Adapt(dbentity);
                await _menuRepository.UpdateAsync(dbentity);
            }
            else
            {
                //if (entities.Any(o => o.MId == input.MId))
                //{
                //    resultdata.Errors = "唯一标识已存在";
                //    return resultdata;
                //}
                var newEntity = await _menuRepository.InsertAsync(input.Adapt<Menu>());
            }

            resultdata.Succeeded = true;
            resultdata.Errors = "成功";
            return resultdata;
        }

        /// <summary>
        /// 删除一条
        /// </summary>
        /// <param name="id"></param>
        public async Task<ResultData<string>> Delete(int id)
        {
            var resultdata = new ResultData<string>();
            var dbmenu = await _menuRepository.DetachedEntities.FirstOrDefaultAsync(o => o.Id == id);
            if (dbmenu.IsSystem == false)
            {
                await _menuRepository.DeleteAsync(id);

                resultdata.Succeeded = true;
                resultdata.Errors = "成功";
                return resultdata;
            }
            else
            {
                resultdata.Errors = "系统菜单不能删除";
                return resultdata;
            }
        }

        /// <summary>
        /// 查询一条[跟踪实体]
        /// </summary>
        /// <param name="id"></param>
        public async Task<MenuOut> Get(int id)
        {
            var entities = await _cacheService.GetMenuEntities();
            var dbentity = entities.FirstOrDefault(o => o.Id == id);
            if (dbentity == null) return null;
            return dbentity.Adapt<MenuOut>();
        }

        /// <summary>
        /// 查询一条[跟踪实体]
        /// </summary>
        /// <param name="mid"></param>
        public async Task<MenuOut> Get(string mid)
        {
            var entities = await _cacheService.GetMenuEntities();
            //var dbentity = entities.FirstOrDefault(o => o.MId == mid);
            //if (dbentity == null) return null;
            //return dbentity.Adapt<MenuDto>();
            return entities.FirstOrDefault(o => o.MId == mid).Adapt<MenuOut>();
        }

        /// <summary>
        /// 分页查询
        /// </summary>
        /// <param name="searchQuery"></param>
        /// <returns></returns>
        public async Task<PagedListToLayui<MenuOut>> GetAllByPageToLayui(MenuQuery searchQuery)
        {
            //var queryable= _menuRepository.DetachedEntities.AsQueryable();
            //if (!string.IsNullOrWhiteSpace(searchQuery.KeyWords))
            //{
            //    var kw = searchQuery.KeyWords.ToLower();
            //    queryable = queryable.Where(o => o.No.Contains(kw));
            //}

            var entities = await _cacheService.GetMenuEntities();
            //var pageResult = entities.OrderByDescending(o => o.Id).ProjectToType<MenuDto>();
            var resultpage = entities.OrderByDescending(o => o.Id).Adapt<List<MenuOut>>().ToPagedListToLayui(searchQuery.Page, searchQuery.Limit);
            foreach (var item in resultpage.data)
            {
                item.PermissionStr = entities.First(o => o.Id == item.Id).Permissions?.Select(o => o.Name)?.StringJoin(",") ?? "";
            }

            return resultpage;
        }

        /// <summary>
        /// 查询菜单下来树
        /// </summary>
        /// <returns></returns>
        public async Task<Dtree> GetDtree(string pid = "")
        {
            var entities = await _cacheService.GetMenuEntities();
            var dtree = entities.Select(o => new DtreeEntity { id = o.MId, pid = o.PMId, name = o.Name, sort = o.Sort }).GetDtree(pid = "");
            return dtree;
        }

        /// <summary>
        /// 设置菜单权限
        /// </summary>
        /// <param name="menuid">菜单id</param>
        /// <param name="permissionstrs">权限字符串，英文逗号隔开</param>
        /// <returns></returns>
        public async Task<ResultData<string>> SetMenuPermission(int menuid, string permissionstrs)
        {
            var resultdata = new ResultData<string>();
            var dbmenu = await _menuRepository.Include(o => o.Permissions).FirstOrDefaultAsync(o => o.Id == menuid);
            var permissions = permissionstrs.ToIntList(new char[] { ',' });
            foreach (var permissionid in dbmenu.Permissions.Select(o => o.Id).ToList())
            {
                var permission = dbmenu.Permissions.First(o => o.Id == permissionid);
                if (permissions.All(o => o != permissionid)) dbmenu.Permissions.Remove(permission);
            }
            dbmenu.MenuPermissions = new List<MenuPermission>();
            foreach (var permissionid in permissions)
            {
                dbmenu.MenuPermissions.Add(new MenuPermission() { PermissionId = permissionid });
            }
            resultdata.Succeeded = true;
            return resultdata;
        }

        /// <summary>
        /// 获取Dtree 树
        /// </summary>
        /// <param name="menuid"></param>
        /// <param name="typecode"></param>
        /// <returns></returns>
        public async Task<Dtree> GetDtreeCheck(int menuid = 0, string typecode = "")
        {
            Menu menu = null;
            if (menuid > 0)
            {
                var menuentities = await _cacheService.GetMenuEntities();
                menu = menuentities.FirstOrDefault(o => o.Id == menuid);
            }
            var entities = await _cacheService.GetPermissionEntities();
            if (!string.IsNullOrWhiteSpace(typecode))
            {
                entities = entities.Where(o => o.TypeCode.ToLower().Trim() == typecode.ToLower().Trim()).ToList();
            }
            var dtree = new Dtree();
            var dtreeitems = new List<DtreeCheckItem>();
            var controllers = entities.Select(o => new { o.Controller, o.ControllerDescription }).Distinct().ToList();
            for (var i = 0; i < controllers.Count; i++)
            {
                var ck = 0;
                var childrenEntities = entities.Where(o => o.Controller.ToLower() == controllers[i].Controller.ToLower());
                var entitiesids = string.Join(",", childrenEntities.Select(i => string.Format("{0}", i.Id)));

                if (menu != null && menu.Permissions != null && menu.Permissions.Count > 0)
                {
                    //var menuentitiesids = string.Join(",",menu.Permissions.Select(o=>$"{o.Id}"));
                    var count = 0;//菜单中已有选中的数量
                    foreach (var menuPermission in menu.Permissions)
                    {
                        if (childrenEntities.Any(o => o.Id == menuPermission.Id))
                        {
                            count++;
                        }
                    }
                    if (menu.Permissions.Count == count)
                    {
                        ck = 1;
                    }
                    else if (count > 0)
                    {
                        ck = 2;
                    }
                }

                DtreeCheckItem dtreeitem = new DtreeCheckItem()
                {
                    id = $"p_{i + 1}",
                    title = controllers[i].ControllerDescription,
                    parentId = "",
                    last = false,
                    checkArr = new Dictionary<string, string>()
                    {
                       { "type","0"},
                       { "checked",$"{ ck}" }
                    }
                };
                foreach (var item in childrenEntities)
                {
                    var ck2 = 0;
                    if (menu != null && menu.Permissions != null && menu.Permissions.Count > 0)
                    {
                        //已有选中
                        if (menu.Permissions.Any(o => o.Id == item.Id)) ck2 = 1;
                    }

                    DtreeCheckItem dtreeitem2 = new DtreeCheckItem()
                    {
                        id = $"{item.Id}",
                        title = item.Name,
                        parentId = dtreeitem.id,
                        last = true,
                        checkArr = new Dictionary<string, string>()
                        {
                           { "type","0"},
                           { "checked",$"{ ck2}" }
                        }
                    };
                    dtreeitem.children.Add(dtreeitem2);
                }
                dtreeitems.Add(dtreeitem);
            }
            dtree.data = dtreeitems;
            return dtree;
        }

        /// <summary>
        /// 设置状态
        /// </summary>
        /// <param name="id"></param>
        /// <param name="state"></param>
        /// <param name="field">字段名</param>
        /// <returns></returns>
        public async Task<ResultData<string>> SetState(int id, bool state, string field)
        {
            var resultdata = new ResultData<string>();
            var entity = await _menuRepository.FirstOrDefaultAsync(o => o.Id == id);

            switch (field.ToLower())
            {
                case "isexpand":
                    {
                        entity.IsExpand = state;
                    }
                    break;
                //case "isdeleted":
                //    {
                //        entity.IsDeleted = state;
                //    }
                //    break;
                //case "isdisuse":
                //    {
                //        entity.IsDisuse = state;
                //    }
                //    break;
                //case "issystem":
                //    {
                //        entity.IsSystem = state;
                //    }
                //    break;
                case "isshow":
                    {
                        entity.IsShow = state;
                    }
                    break;

                case "isenable":
                    {
                        entity.IsEnable = state;
                    }
                    break;

                default:
                    break;
            }

            resultdata.Succeeded = true;
            resultdata.Errors = "成功";
            return resultdata;
        }

        #region 默认未启用

        ///// <summary>
        ///// 新增一条
        ///// </summary>
        ///// <param name="input"></param>
        ///// <returns></returns>
        //public async Task<ResultData<string>> Insert(MenuInput input)
        //{
        //    var resultdata = new ResultData<string>();
        //    var newEntity = await _menuRepository.InsertAsync(input.Adapt<Menu>());
        //
        //    resultdata.Succeeded = true;
        //    resultdata.Errors = "成功";
        //    return resultdata;
        //}
        //
        ///// <summary>
        ///// 更新一条
        ///// </summary>
        ///// <param name="input"></param>
        ///// <returns></returns>
        //public async Task<ResultData<string>> Update(int id,MenuInput input)
        //{
        //    var resultdata=new ResultData<string>();
        //    var dbentity = await _menuRepository.FindAsync(id);
        //    input.Adapt(dbentity);
        //    await _menuRepository.UpdateAsync(dbentity);
        //
        //    resultdata.Succeeded = true;
        //    resultdata.Errors = "成功";
        //    return resultdata;
        //}
        //
        ///// <summary>
        ///// 新增或更新多条
        ///// </summary>
        ///// <param name="inputs"></param>
        ///// <returns></returns>
        //public async Task<ResultData<string>> Inserts(List<MenuInput> inputs)
        //{
        //    var resultdata = new ResultData<string>();
        //    var dbaddinputs = inputs.Adapt<List<Menu>>();
        //    await _menuRepository.InsertAsync(dbaddinputs);
        //    resultdata.Succeeded = true;
        //    resultdata.Errors = "成功";
        //    return resultdata;
        //}
        ///// <summary>
        ///// 新增或更新多条
        ///// </summary>
        ///// <param name="inputs"></param>
        ///// <returns></returns>
        //public async Task<ResultData<string>> Updates(List<MenuInput> inputs)
        //{
        //    var resultdata = new ResultData<string>();
        //    var ids = inputs.Select(o => o.Id).ToList();
        //    var dbentitys = await _menuRepository.Where(u => ids.Any(a => a == u.Id)).ToListAsync();
        //    inputs.Adapt(dbentitys);
        //    await _menuRepository.UpdateAsync(dbentitys);
        //
        //    resultdata.Succeeded = true;
        //    resultdata.Errors = "成功";
        //    return resultdata;
        //}
        //
        ///// <summary>
        ///// 新增或更新多条
        ///// </summary>
        ///// <param name="input"></param>
        ///// <returns></returns>
        //public async Task<ResultData<string>> InsertOrUpdates(List<MenuInput> inputs)
        //{
        //    var resultdata = new ResultData<string>();
        //    if (inputs.Any(o => o.Id > 0))
        //    {
        //        var updates = inputs.Where(o => o.Id > 0);
        //        var ids = updates.Select(o=>o.Id).ToList();
        //        var dbentity =  _menuRepository.Where(o=> ids.Any(a=>a==o.Id));
        //        inputs.Adapt(dbentity);
        //        await  _menuRepository.UpdateAsync(dbentity);
        //    }
        //    else
        //    {
        //       var adds = inputs.Where(o => o.Id <= 0);
        //       await _menuRepository.InsertAsync(adds.Adapt<List<Menu>>());
        //
        //    }
        //    resultdata.Succeeded = true;
        //    resultdata.Errors = "成功";
        //    return resultdata;
        //}
        //
        //
        ///// <summary>
        ///// 查询所有
        ///// </summary>
        ///// <returns></returns>
        //public async Task<List<MenuDto>> GetAll()
        //{
        //    var entities = _menuRepository.DetachedEntities.AsQueryable().ProjectToType<MenuDto>();
        //    var datas= await entities.ToListAsync();
        //    datas.SetMemberCache("Table_Menu");
        //    return datas;
        //}
        ///// <summary>
        ///// 分页查询
        ///// </summary>
        ///// <param name="searchQuery"></param>
        ///// <returns></returns>
        //public async Task<PagedList<MenuDto>> GetAllByPage(MenuQuery searchQuery)
        //{
        //    //var queryable= _menuRepository.DetachedEntities.AsQueryable(tracking:false);
        //    //if (!string.IsNullOrWhiteSpace(searchQuery.KeyWords))
        //    //{
        //    //    var kw = searchQuery.KeyWords.ToLower();
        //    //    queryable = queryable.Where(o => o.No.Contains(kw));
        //    //}
        //    var pageResult = _menuRepository.DetachedEntities.AsQueryable().OrderByDescending(o => o.Id).ProjectToType<MenuDto>();
        //
        //    return await pageResult.ToPagedListAsync(searchQuery.Page, searchQuery.Limit);
        //}
        //
        //
        //
        //

        #endregion 默认未启用
    }

    public interface IMenuService
    {
        /// <summary>
        /// 新增或更新一条
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        Task<ResultData<string>> InsertOrUpdate(MenuInput input);

        /// <summary>
        /// 删除一条
        /// </summary>
        /// <param name="id"></param>
        Task<ResultData<string>> Delete(int id);

        /// <summary>
        /// 查询一条
        /// </summary>
        /// <param name="id"></param>
        Task<MenuOut> Get(int id);

        /// <summary>
        /// 查询一条[跟踪实体]
        /// </summary>
        /// <param name="mid"></param>
        Task<MenuOut> Get(string mid);

        /// <summary>
        /// 分页查询
        /// </summary>
        /// <param name="searchQuery"></param>
        /// <returns></returns>
        Task<PagedListToLayui<MenuOut>> GetAllByPageToLayui(MenuQuery searchQuery);

        /// <summary>
        /// 查询菜单下来树
        /// </summary>
        /// <returns></returns>
        Task<Dtree> GetDtree(string pid = "");

        /// <summary>
        /// 设置菜单权限
        /// </summary>
        /// <param name="menuid">菜单id</param>
        /// <param name="permissionstrs">权限字符串，英文逗号隔开</param>
        /// <returns></returns>
        Task<ResultData<string>> SetMenuPermission(int menuid, string permissionstrs);

        /// <summary>
        /// 获取Dtree 树
        /// </summary>
        /// <param name="menuid"></param>
        /// <param name="typecode"></param>
        /// <returns></returns>
        Task<Dtree> GetDtreeCheck(int menuid, string typecode = "");

        /// <summary>
        /// 设置状态
        /// </summary>
        /// <param name="id"></param>
        /// <param name="state"></param>
        /// <param name="field">字段名</param>
        /// <returns></returns>
        Task<ResultData<string>> SetState(int id, bool state, string field);

        #region 默认未启用

        ///// <summary>
        ///// 新增一条
        ///// </summary>
        ///// <param name="input"></param>
        ///// <returns></returns>
        //Task<ResultData<string>> Insert(MenuInput input);
        //
        ///// <summary>
        ///// 更新一条
        ///// </summary>
        ///// <param name="input"></param>
        ///// <returns></returns>
        //Task<ResultData<string>> Update(int id,MenuInput input);
        ///// <summary>
        ///// 新增或更新一条
        ///// </summary>
        ///// <param name="input"></param>
        ///// <returns></returns>
        //Task<ResultData<string>> Inserts(List<MenuInput> inputs);
        ///// <summary>
        ///// 新增或更新多条
        ///// </summary>
        ///// <param name="inputs"></param>
        ///// <returns></returns>
        //Task<ResultData<string>> Updates(List<MenuInput> inputs);
        ///// <summary>
        ///// 新增或更新多条
        ///// </summary>
        ///// <param name="inputs"></param>
        ///// <returns></returns>
        //Task<ResultData<string>> InsertOrUpdates(List<MenuInput> inputs);
        ///// <summary>
        ///// 查询所有
        ///// </summary>
        ///// <returns></returns>
        //Task<List<MenuDto>> GetAll();
        ///// <summary>
        ///// 分页查询
        ///// </summary>
        ///// <param name="searchQuery"></param>
        ///// <returns></returns>
        //Task<PagedList<MenuDto>> GetAllByPage(MenuQuery searchQuery);

        #endregion 默认未启用
    }
}